package com.wondream.myframework.app.basictest.compiler;

import javax.tools.*;
import java.io.File;
import java.lang.reflect.Method;
import java.net.URL;
import java.net.URLClassLoader;
import java.nio.charset.StandardCharsets;
import java.util.Collections;

/**
 * 动态编译java类，产生文件
 * @author wangjun
 * @note DynamicCompilationExample
 * @date 2023-10-12  17:36
 */
public class DynamicCompilationExample {

    // 内存直接动态编译
    public static void main(String[] args) throws Exception {
        //1. 获取 `JavaCompiler` 实例
        JavaCompiler compiler = ToolProvider.getSystemJavaCompiler();
        //2. 获取 `DiagnosticCollector `实例
        DiagnosticCollector<JavaFileObject> diagnostics = new DiagnosticCollector<>();
        //3. 获取 `StandardJavaFileManager` 实例
        StandardJavaFileManager fileManager = compiler.getStandardFileManager(diagnostics, null, null);

        //4. 自定义实例
        String code = "public class HelloWorld {\n" +
                "    public static void main(String[] args) {\n" +
                "        System.out.println(\"Hello, world!\");\n" +
                "    }\n" +
                "}";
        JavaFileObject source = new JavaSourceFileObject("HelloWorld", code, StandardCharsets.UTF_8);

        //5. 创建` CompilationTask` 实例
        Iterable<? extends JavaFileObject> compilationUnits = Collections.singletonList(source);
        JavaCompiler.CompilationTask task = compiler.getTask(null, fileManager, diagnostics, null, null, compilationUnits);
        //6. 调用` CompilationTask `的` call() `方法
        boolean success = task.call();

        //7. 关闭文件管理器
        fileManager.close();

        if (success) {
            System.out.println("Compilation succeeded.");
            //8. 反射使用
            URLClassLoader classLoader = new URLClassLoader(new URL[]{new File(".").toURI().toURL()});
            Class<?> clazz = classLoader.loadClass("HelloWorld");
            Method method = clazz.getMethod("main", String[].class);
            method.invoke(null, new Object[]{null});
        } else {
            System.out.println("Compilation failed.");
            for (Diagnostic<? extends JavaFileObject> diagnostic : diagnostics.getDiagnostics()) {
                System.out.println(diagnostic.getMessage(null));
            }
        }
    }
}

